<?php
declare (strict_types = 1);

namespace app\command;

use think\console\Command;
use think\console\Input;
use think\console\Output;
use think\facade\Db;
use app\service\TopviewApiService;
use app\service\OssService;

class SyncCaptionStyles extends Command
{
    protected function configure()
    {
        $this->setName('sync:caption-styles')
            ->setDescription('同步字幕样式列表并上传缩略图到OSS');
    }

    protected function execute(Input $input, Output $output)
    {
        $output->writeln('开始同步字幕样式列表...');

        $apiService = new TopviewApiService();
        $ossService = new OssService();
        $syncCount = 0;
        $uploadCount = 0;
        $errorCount = 0;

        try {
            // 从API获取字幕样式列表
            $output->writeln('正在从API获取字幕样式列表...');
            $captionList = $apiService->getCaptionList();

            if (empty($captionList) || !is_array($captionList)) {
                $output->writeln('API返回的字幕样式列表为空');
                return 0;
            }

            $output->writeln("获取到 " . count($captionList) . " 个字幕样式");

            foreach ($captionList as $caption) {
                try {
                    $captionId = $caption['captionId'] ?? '';
                    $thumbnail = $caption['thumbnail'] ?? '';

                    if (empty($captionId)) {
                        $output->writeln("跳过无效的字幕样式（缺少captionId）");
                        continue;
                    }

                    $output->writeln("处理字幕样式: {$captionId}");

                    // 检查是否已存在
                    $existing = Db::name('caption_styles')
                        ->where('caption_id', $captionId)
                        ->find();

                    $ossThumbnailUrl = '';
                    
                    // 如果有缩略图URL，上传到OSS
                    if (!empty($thumbnail)) {
                        try {
                            $output->writeln("  正在上传缩略图到OSS: {$thumbnail}");
                            
                            // 使用cURL下载图片内容（带重试）
                            $imageContent = $this->downloadImageWithRetry($thumbnail, 10);
                            if ($imageContent === false) {
                                throw new \Exception("无法下载缩略图: {$thumbnail}");
                            }

                            // 生成OSS对象名
                            $extension = pathinfo(parse_url($thumbnail, PHP_URL_PATH), PATHINFO_EXTENSION);
                            if (empty($extension)) {
                                $extension = 'jpg'; // 默认扩展名
                            }
                            $objectName = 'caption/thumbnails/' . date('Ymd') . '/' . $captionId . '.' . $extension;

                            // 创建临时文件
                            $tempFile = tempnam(sys_get_temp_dir(), 'caption_thumb_');
                            file_put_contents($tempFile, $imageContent);

                            try {
                                // 上传到OSS
                                $ossThumbnailUrl = $ossService->putObject($objectName, $tempFile);
                                $output->writeln("  缩略图上传成功: {$ossThumbnailUrl}");
                                $uploadCount++;
                            } finally {
                                // 清理临时文件
                                @unlink($tempFile);
                            }
                        } catch (\Exception $e) {
                            $output->writeln("  缩略图上传失败: " . $e->getMessage());
                            // 继续处理，不中断整个流程
                        }
                    }

                    // 更新或插入数据库记录
                    $data = [
                        'caption_id' => $captionId,
                        'thumbnail' => $thumbnail,
                        'oss_thumbnail_url' => $ossThumbnailUrl,
                        'status' => 1,
                        'update_time' => date('Y-m-d H:i:s')
                    ];

                    if ($existing) {
                        // 更新现有记录
                        Db::name('caption_styles')
                            ->where('caption_id', $captionId)
                            ->update($data);
                        $output->writeln("  更新字幕样式记录");
                    } else {
                        // 插入新记录
                        $data['create_time'] = date('Y-m-d H:i:s');
                        Db::name('caption_styles')->insert($data);
                        $output->writeln("  新增字幕样式记录");
                    }

                    $syncCount++;

                    // 避免请求过于频繁
                    usleep(200000); // 0.2秒

                } catch (\Exception $e) {
                    $output->writeln("处理字幕样式 {$captionId} 失败: " . $e->getMessage());
                    $errorCount++;
                }
            }

            $output->writeln("同步完成！");
            $output->writeln("总计处理: {$syncCount} 个字幕样式");
            $output->writeln("成功上传缩略图: {$uploadCount} 个");
            $output->writeln("处理失败: {$errorCount} 个");

        } catch (\Exception $e) {
            $output->writeln('同步字幕样式时发生错误: ' . $e->getMessage());
            return 1;
        }

        return 0;
    }

    /**
     * 使用cURL下载图片（带重试机制）
     * @param string $url 图片URL
     * @param int $maxRetries 最大重试次数
     * @return string|false 图片内容或false
     */
    private function downloadImageWithRetry($url, $maxRetries = 10)
    {
        $lastException = null;
        
        for ($attempt = 1; $attempt <= $maxRetries; $attempt++) {
            try {
                return $this->downloadImage($url);
            } catch (\Exception $e) {
                $lastException = $e;
                $output = new \think\console\Output();
                $output->writeln("  下载图片失败 (尝试 {$attempt}/{$maxRetries}) - URL: {$url}, 错误: " . $e->getMessage());
                
                // 如果不是最后一次尝试，等待一段时间后重试
                if ($attempt < $maxRetries) {
                    $waitTime = pow(2, $attempt - 1); // 指数退避：1秒, 2秒, 4秒
                    $output->writeln("  等待 {$waitTime} 秒后重试...");
                    sleep($waitTime);
                }
            }
        }
        
        // 所有重试都失败了
        throw new \Exception("下载失败，已重试 {$maxRetries} 次。最后错误: " . $lastException->getMessage());
    }

    /**
     * 使用cURL下载图片
     * @param string $url 图片URL
     * @return string|false 图片内容或false
     */
    private function downloadImage($url)
    {
        $ch = curl_init();
        curl_setopt($ch, CURLOPT_URL, $url);
        curl_setopt($ch, CURLOPT_RETURNTRANSFER, true);
        curl_setopt($ch, CURLOPT_FOLLOWLOCATION, true); // 跟随重定向
        curl_setopt($ch, CURLOPT_SSL_VERIFYPEER, false); // 跳过SSL验证
        curl_setopt($ch, CURLOPT_SSL_VERIFYHOST, false);
        curl_setopt($ch, CURLOPT_TIMEOUT, 30); // 30秒超时
        curl_setopt($ch, CURLOPT_CONNECTTIMEOUT, 10); // 10秒连接超时
        curl_setopt($ch, CURLOPT_USERAGENT, 'Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/91.0.4472.124 Safari/537.36');
        curl_setopt($ch, CURLOPT_HTTPHEADER, [
            'Accept: image/webp,image/apng,image/*,*/*;q=0.8',
            'Accept-Language: zh-CN,zh;q=0.9,en;q=0.8',
            'Cache-Control: no-cache',
        ]);
        
        $content = curl_exec($ch);
        $httpCode = curl_getinfo($ch, CURLINFO_HTTP_CODE);
        $error = curl_error($ch);
        curl_close($ch);
        
        if ($error) {
            throw new \Exception("cURL错误: {$error}");
        }
        
        if ($httpCode !== 200) {
            throw new \Exception("HTTP错误: {$httpCode}");
        }
        
        if ($content === false) {
            throw new \Exception("下载失败");
        }
        
        // 检查内容是否为空
        if (empty($content)) {
            throw new \Exception("下载的内容为空");
        }
        
        return $content;
    }
}
